package dp.mobile.comm.worker;

import java.io.ObjectInputStream;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;
import dp.mobile.comm.ICommHandler;

public class BluetoothHandler {
	public static final int STATE_DISCONNECTED = 0;
	public static final int STATE_LISTENING = 1;
	public static final int STATE_CONNECTING = 2;
	public static final int STATE_CONNECTED = 3;
	
	private ICommHandler mEventHandler = null;
	private static BluetoothHandler instance = null;
	private BluetoothAdapter mAdapter;
	private BluetoothSocket mConnectedSocket = null;
    //private BluetoothDevice mConnectedDevice = null;
    private Courier mCourier = null;
    private Acceptor mAcceptor = null;
    private Connector mConnector = null;
    private int mState;
	
	private BluetoothHandler() {
		mAdapter = BluetoothAdapter.getDefaultAdapter();
	}
	
	public void setState(int state) {
		mState = state;
	}
	
	public void finish() {
		if (mAdapter!=null && mAdapter.isEnabled())
			mAdapter.disable();
	}
	
	public void reset() {
		if (mState == STATE_CONNECTED && mCourier != null && mCourier.isAlive()) {
			mCourier.cancel();
			Log.i("this" , "COURIER CANCELLED");
		}
		
		if (mState == STATE_LISTENING && mAcceptor != null && mAcceptor.isAlive()) {
			mAcceptor.cancel();
			Log.i("this" , "ACCEPTOR CANCELLED");
		}
		
		if (mState == STATE_CONNECTING && mConnector != null && mConnector.isAlive()) {
			mConnector.cancel();
			Log.i("this" , "CONNECTOR CANCELLED");
		}
		//mConnectedDevice = null;
		mConnectedSocket = null;
		
		mState = STATE_DISCONNECTED;
	}
	
	public BluetoothAdapter getAdapter() {
		return mAdapter;
	}
	
	public void setConnectedSocket(BluetoothSocket sock) {
		mConnectedSocket = sock;
	}
	
	/*public void setConnectedDevice(BluetoothDevice device) {
		mConnectedDevice = device;
	}*/
	
	public void setEventHandler(ICommHandler handler) {
		mEventHandler = handler;
		/*if (mCourier != null)
			mCourier.setEventHandler(mEventHandler);*/
	}
	
	public static BluetoothHandler getInstance() {
		if (instance == null) {
			instance = new BluetoothHandler();
		}
		
		return instance;
	}
	
	public void connect(BluetoothDevice device) {
		//mConnectedDevice = device;
		mConnector = new Connector(this , device);
		mConnector.start();
		mState = STATE_CONNECTING;
	}
	
	void connected(BluetoothSocket socket) {
		mConnectedSocket = socket;
		if (mEventHandler != null) mEventHandler.onConnected();
		mState = STATE_CONNECTED;
		openChannel();
	}
	
	void connectFailed() {
		if (mEventHandler != null) mEventHandler.onConnectFailed();
	}
	
	void listenFailed() {
		if (mEventHandler != null) mEventHandler.onAcceptFailed();
	}
	
	void connectionFailed() {
		if (mEventHandler != null) mEventHandler.onConnectionFailed();
	}
	
	void objectReceived(int objId , ObjectInputStream ois) {
		if (mEventHandler != null) mEventHandler.onObjectReceived(objId, ois);
	}
	
	/*public void reconnect(BluetoothDevice device) {
		mConnectedDevice = device;
		try {
			mConnectedSocket = device.createRfcommSocketToServiceRecord(CommAsyncHelper.EDEN_UUID);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}*/
	
	public void disconnect() {
		if (mState == STATE_CONNECTED) {
			if (mCourier != null && mCourier.isAlive()) {
				mCourier.cancel();
				Log.i("this" , "COURIER CANCELLED");
			}
			
			mConnectedSocket = null;
			mState = STATE_DISCONNECTED;
		}
	}
	
	private void openChannel() {
		mCourier = new Courier(this , mConnectedSocket);
		mCourier.start();
		Log.i("this" , "CHANNEL OPENED");
	}
	
	public BluetoothDevice getConnectedDevice() {
		if (mConnectedSocket != null)
			return mConnectedSocket.getRemoteDevice();
		else
			return null;
	}
	
	public boolean isConnected() {
		return /*mConnectedDevice != null &&*/ mConnectedSocket != null && mCourier.isAlive();
	}
	
	public void init() {
		
	}
	
	public void startServer() {
		mAcceptor = new Acceptor(mAdapter, this);
		mAcceptor.start();
		mState = STATE_LISTENING;
	}
	
	public void send(Object o) {
		mCourier.sendObject(o);
		//Log.i("this" , o.getClass().toString());
	}
	
	public void sendObjectId(int id) {
		mCourier.sendInt(id);
	}
}
